"""
音频处理API蓝图
提供音频提取、音频合并等功能
"""

from flask import Blueprint, request, jsonify, send_file, current_app
import os
import json
import logging
from app.service.audio_service import AudioService
from app.tools.utils import get_safe_filename, validate_file_extension

# 创建音频API蓝图
audio_bp = Blueprint('audio', __name__, url_prefix='/audio')

def allowed_file(filename, allowed_extensions):
    """检查文件格式是否允许"""
    return validate_file_extension(filename, allowed_extensions)

def get_audio_service():
    """获取音频服务实例"""
    return AudioService(current_app.config['UPLOAD_FOLDER'], current_app.config['OUTPUT_FOLDER'])

@audio_bp.route('/extract', methods=['POST'])
def extract_audio():
    """提取视频中的音频"""
    try:
        if 'video' not in request.files:
            return jsonify({'error': '没有上传视频文件'}), 400
        
        file = request.files['video']
        if file.filename == '':
            return jsonify({'error': '没有选择文件'}), 400
        
        if not allowed_file(file.filename, current_app.config['ALLOWED_EXTENSIONS']):
            return jsonify({'error': '不支持的文件格式'}), 400
        
        # 保存上传的文件
        filename = get_safe_filename(file.filename)
        temp_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
        file.save(temp_path)
        
        # 提取音频
        audio_service = get_audio_service()
        result = audio_service.extract_audio_service(temp_path)
        if not result['success']:
            # 清理临时文件
            if os.path.exists(temp_path):
                os.remove(temp_path)
            return jsonify({'error': result['error']}), 500
        
        output_path = result['output_path']
        
        # 检查输出文件是否存在
        if not os.path.exists(output_path):
            # 清理临时文件
            if os.path.exists(temp_path):
                os.remove(temp_path)
            return jsonify({'error': f'输出文件不存在: {output_path}'}), 500
        
        # 清理临时文件
        if os.path.exists(temp_path):
            os.remove(temp_path)
        
        # 获取文件名用于下载
        output_filename = os.path.basename(output_path)
        
        return send_file(
            output_path, 
            as_attachment=True, 
            download_name=output_filename,
            mimetype='audio/mpeg'
        )
    
    except Exception as e:
        logging.error(f"音频提取失败: {e}")
        # 确保清理临时文件
        try:
            if 'temp_path' in locals() and os.path.exists(temp_path):
                os.remove(temp_path)
        except:
            pass
        return jsonify({'error': str(e)}), 500

@audio_bp.route('/merge', methods=['POST'])
def merge_audio():
    """合并音频文件"""
    try:
        if 'audio1' not in request.files or 'audio2' not in request.files:
            return jsonify({'error': '需要上传两个音频文件'}), 400
        
        audio1 = request.files['audio1']
        audio2 = request.files['audio2']
        
        if not (allowed_file(audio1.filename, current_app.config['ALLOWED_EXTENSIONS']) and 
                allowed_file(audio2.filename, current_app.config['ALLOWED_EXTENSIONS'])):
            return jsonify({'error': '不支持的文件格式'}), 400
        
        # 保存上传的文件
        temp_path1 = os.path.join(current_app.config['UPLOAD_FOLDER'], get_safe_filename(audio1.filename))
        temp_path2 = os.path.join(current_app.config['UPLOAD_FOLDER'], get_safe_filename(audio2.filename))
        
        audio1.save(temp_path1)
        audio2.save(temp_path2)
        
        # 合并音频
        audio_service = get_audio_service()
        result = audio_service.merge_audio_service([temp_path1, temp_path2])
        if not result['success']:
            # 清理临时文件
            for temp_path in [temp_path1, temp_path2]:
                if os.path.exists(temp_path):
                    os.remove(temp_path)
            return jsonify({'error': result['error']}), 500
        
        output_path = result['output_path']
        
        # 检查输出文件是否存在
        if not os.path.exists(output_path):
            # 清理临时文件
            for temp_path in [temp_path1, temp_path2]:
                if os.path.exists(temp_path):
                    os.remove(temp_path)
            return jsonify({'error': f'输出文件不存在: {output_path}'}), 500
        
        # 清理临时文件
        for temp_path in [temp_path1, temp_path2]:
            if os.path.exists(temp_path):
                os.remove(temp_path)
        
        # 获取文件名用于下载
        output_filename = os.path.basename(output_path)
        
        return send_file(
            output_path, 
            as_attachment=True, 
            download_name=output_filename,
            mimetype='audio/mpeg'
        )
    
    except Exception as e:
        logging.error(f"音频合并失败: {e}")
        # 确保清理临时文件
        try:
            for temp_path in [temp_path1, temp_path2]:
                if 'temp_path' in locals() and os.path.exists(temp_path):
                    os.remove(temp_path)
        except:
            pass
        return jsonify({'error': str(e)}), 500

@audio_bp.route('/merge_with_timestamps', methods=['POST'])
def merge_audio_with_timestamps():
    """根据时间戳合并音频文件，在空白处添加静音"""
    try:
        # 检查请求数据 - 支持JSON格式和multipart/form-data格式
        if request.is_json:
            data = request.get_json()
        elif 'data' in request.form:
            try:
                data = json.loads(request.form['data'])
            except json.JSONDecodeError:
                return jsonify({'error': 'data字段必须是有效的JSON格式'}), 400
        else:
            return jsonify({'error': '缺少data字段，请使用JSON格式或multipart/form-data格式'}), 400
        
        # 验证必需字段
        if 'timestamps' not in data:
            return jsonify({'error': '缺少timestamps字段'}), 400
        
        timestamps = data['timestamps']
        if not isinstance(timestamps, list) or not timestamps:
            return jsonify({'error': 'timestamps必须是非空数组'}), 400
        
        # 验证时间戳格式
        for ts in timestamps:
            if not isinstance(ts, dict) or 'start_time' not in ts or 'end_time' not in ts:
                return jsonify({'error': '时间戳格式错误，每个时间戳必须包含start_time和end_time'}), 400
        
        # 获取可选的路径参数
        custom_path = data.get('path', None)
        
        # 处理音频文件
        audio_paths = []
        
        # 从指定路径或upload文件夹中读取文件
        if 'files' in data and data['files']:
            if not isinstance(data['files'], list):
                return jsonify({'error': 'files必须是数组'}), 400
            
            # 使用自定义路径或默认的UPLOAD_FOLDER
            base_folder = os.path.join(current_app.config['UPLOAD_FOLDER'], custom_path) if custom_path else current_app.config['UPLOAD_FOLDER']
            logging.info(f"从文件夹读取文件: {base_folder}, 文件列表: {data['files']}")
            
            for i, filename in enumerate(data['files']):
                file_path = os.path.join(base_folder, filename)
                logging.debug(f"文件路径: {file_path}")
                
                if not os.path.exists(file_path):
                    return jsonify({'error': f'文件不存在: {filename}'}), 404
                
                if not allowed_file(filename, current_app.config['ALLOWED_EXTENSIONS']):
                    return jsonify({'error': f'不支持的文件格式: {filename}'}), 400
                
                audio_paths.append(file_path)
                logging.info(f"找到文件 {i}: {filename} -> {file_path}")
        
        # 如果没有指定files，尝试从request.files中获取（向后兼容）
        elif request.files:
            logging.info(f"从request.files读取文件: {list(request.files.keys())}")
            
            for i, (key, file) in enumerate(request.files.items()):
                if file.filename == '':
                    continue
                
                if not allowed_file(file.filename, current_app.config['ALLOWED_EXTENSIONS']):
                    return jsonify({'error': f'不支持的文件格式: {file.filename}'}), 400
                
                # 保存上传的文件到upload文件夹
                safe_filename = get_safe_filename(file.filename)
                upload_path = os.path.join(current_app.config['UPLOAD_FOLDER'], safe_filename)
                file.save(upload_path)
                
                audio_paths.append(upload_path)
                logging.info(f"上传并保存文件 {i}: {file.filename} -> {upload_path}")
        
        # 处理文件URL
        if 'file_urls' in data and data['file_urls']:
            if not isinstance(data['file_urls'], list):
                return jsonify({'error': 'file_urls必须是数组'}), 400
            
            # 这里可以添加从URL下载文件的逻辑
            # 暂时返回错误，提示需要实现URL下载功能
            return jsonify({'error': 'file_urls功能暂未实现，请使用files上传文件'}), 400
        
        # 检查音频文件数量是否与时间戳数量匹配
        if len(audio_paths) != len(timestamps):
            return jsonify({'error': f'音频文件数量({len(audio_paths)})与时间戳数量({len(timestamps)})不匹配'}), 400
        
        # 读取可选增益参数
        gain_db = data.get('gain_db')
        gains_db = data.get('gains_db')
        
        # 根据时间戳合并音频
        audio_service = get_audio_service()
        result = audio_service.merge_audio_with_timestamps_service(
            audio_paths,
            timestamps,
            gain_db=gain_db,
            gains_db=gains_db,
        )
        
        if not result['success']:
            return jsonify({'error': result['error']}), 500
        
        output_path = result['output_path']
        
        # 检查输出文件是否存在
        if not os.path.exists(output_path):
            return jsonify({'error': f'输出文件不存在: {output_path}'}), 500
        
        # 获取文件名用于下载
        output_filename = os.path.basename(output_path)
        
        return send_file(
            output_path, 
            as_attachment=True, 
            download_name=output_filename,
            mimetype='audio/mpeg'
        )
    
    except Exception as e:
        logging.error(f"根据时间戳合并音频失败: {e}")
        # 确保清理临时文件
        try:
            if 'temp_paths' in locals():
                for temp_path in temp_paths:
                    if os.path.exists(temp_path):
                        os.remove(temp_path)
        except:
            pass
        return jsonify({'error': str(e)}), 500 